﻿// UdpClient.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <boost/asio.hpp>

#ifdef _UNICODE
typedef std::wstring STRING;
#else
typedef std::string STRING;
#endif
const size_t NPOS = STRING::npos;

using boost::asio::ip::tcp;

const TCHAR Qt5AppClassName[] = { _T("Qt5QWindowIcon") };
const TCHAR* AxisAppName[] = {
	_T("Axis Legacy"),
	_T("Axis Neuron")
};

int MakeKeyLPARAM(/* int VirtualKey ,*/ int flag)
{
	UINT sCode;
	//Firstbyte ; lparam 参数的 24-31位
	UINT Firstbyte;
	switch (flag)
	{
	case WM_KEYDOWN:    Firstbyte = 0;   break;
	case WM_KEYUP:      Firstbyte = 0xC0; break;
	case WM_CHAR:       Firstbyte = 0x20; break;
	case WM_SYSKEYDOWN: Firstbyte = 0x20; break;
	case WM_SYSKEYUP:   Firstbyte = 0xE0; break;
	case WM_SYSCHAR:    Firstbyte = 0xE0; break;
	}
	// 键的扫描码; lparam 参数 的 16-23位
	// 16–23 Specifies the scan code. 
	// UINT iKey = MapVirtualKey(VirtualKey, 0);
	// 1为 lparam 参数的 0-15位，即发送次数
	// 0–15 Specifies the repeat count for the current message. 
	sCode = (Firstbyte << 24) + 1;// + (iKey << 16) + 1; 
	return sCode;
}

BOOL CALLBACK MyEnumWindowsProc(HWND hWnd, LPARAM lParam) {
	TCHAR* clsName = new TCHAR[32];
	::GetClassName(hWnd, clsName, 32);
	if (_tcscmp(Qt5AppClassName, clsName) != 0) {
		return TRUE;
	}
	delete[] clsName;

	int len = ::GetWindowTextLength(hWnd);
	TCHAR* titleS = new TCHAR[len + 1];
	::GetWindowText(hWnd, titleS, len+1);
	STRING title(titleS);
	delete[] titleS;

	if ((title.find(AxisAppName[0], 0) != NPOS) || (title.find(AxisAppName[1], 0) != NPOS)) {
		*(HWND*)lParam = hWnd;
		return FALSE;
	}
	else {
		return TRUE;
	}
}

HWND MyFindAxisWindow() {
	HWND hMainWnd = 0;
	::EnumWindows(MyEnumWindowsProc, (LPARAM)&hMainWnd);
	if (!hMainWnd) {
		::MessageBox(nullptr, _T("Axis software not running..."), _T("Error:"), MB_OK);
		return 0;
	}
	else {
		return hMainWnd;
	}
}

HWND MyFindWindow(int which)
{
	TCHAR* A_szWinName[2] = {
		_T("Record Settings"),
		_T("MotionCaptureToolBarWindow")
	};

	HWND hLastWin = ::FindWindow(Qt5AppClassName, A_szWinName[which]);
	return hLastWin;
}

void ClickRecordButton(HWND hMainWnd_) {
	/*HWND hWnd_RecordButton = MyFindWindow(1);

	RECT rc;
	if (::GetClientRect(hWnd_RecordButton, &rc)) {
		int x = rc.right - 20;
		int y = rc.bottom - 34;
		POINT pt{ x, y };
		::ClientToScreen(hWnd_RecordButton, &pt);
		::SetCursorPos(pt.x, pt.y);

		LPARAM lParam = (y << 16) | x;
		WPARAM wParam = MK_LBUTTON;
		::PostMessage(hWnd_RecordButton, WM_LBUTTONDOWN, wParam, lParam);
		::PostMessage(hWnd_RecordButton, WM_LBUTTONUP, wParam, lParam);
	}*/

	/*LPARAM lParam = (MOD_CONTROL << 16) | 'R';
	::PostMessage(hMainWnd_, WM_HOTKEY, 0, lParam);*/

	/*INPUT input;
	input.type = INPUT_KEYBOARD;
	input.ki.wVk = 'R';
	{
		INPUT_KEYBOARD,
		{
			INPUT_KEYBOARD,
			'R',
			
		}
	};
	::SendInput(1, &input, sizeof(INPUT));*/
}

void StartRecord(HWND hMainWnd_) {
	HWND hWnd_RecordSettings = MyFindWindow(0);
	if (!hWnd_RecordSettings) {
		ClickRecordButton(hMainWnd_);
		hWnd_RecordSettings = MyFindWindow(0);
	}
	if (!hWnd_RecordSettings) {
		::MessageBox(nullptr, _T("Please open [Record Settings] window..."), _T("Error:"), MB_OK);
		return;
	}

	RECT rc;
	if (::GetClientRect(hWnd_RecordSettings, &rc)) {
		int x = rc.right - 125;
		int y = rc.bottom - 25;
		POINT pt{ x, y };
		::ClientToScreen(hWnd_RecordSettings, &pt);
		::SetCursorPos(pt.x, pt.y);

		LPARAM lParam = (y << 16) | x;
		WPARAM wParam = MK_LBUTTON;
		::PostMessage(hWnd_RecordSettings, WM_LBUTTONDOWN, wParam, lParam);
		::PostMessage(hWnd_RecordSettings, WM_LBUTTONUP, wParam, lParam);
	}
}

int main()
{
	HWND hMainWnd = MyFindAxisWindow();
	if (!hMainWnd) {
		return 0;
	}

	namespace ip = boost::asio::ip;
	boost::asio::io_service io_service;
	ip::udp::socket socket(io_service);

	unsigned short multicast_port = 8877;
	ip::udp::endpoint listen_endpoint(ip::udp::v4(), multicast_port);
	ip::address multicast_address = ip::address::from_string("239.255.33.44").to_v4();

	socket.open(listen_endpoint.protocol());
	socket.set_option(ip::multicast::join_group(multicast_address));

	ip::udp::endpoint sender_endpoint;

	// Receive data.
	//boost::array<char, 4> buffer;
	char buf[500] = { 0 };
	while (true) {
		std::size_t bytes_transferred =
			socket.receive_from(boost::asio::buffer(buf), sender_endpoint);

		std::cout << "got " << bytes_transferred << " bytes." << buf << std::endl;

		::SetForegroundWindow(hMainWnd);
		::SetFocus(hMainWnd);

		StartRecord(hMainWnd);
	}

	return 0;
}

